package com.nbsaas.boot.service;

import com.nbsaas.boot.NacosRegistryAdapter;
import com.nbsaas.boot.PolarisRegistryAdapter;
import com.nbsaas.boot.api.adapter.RegistryAdapter;
import com.nbsaas.boot.api.adapter.ServiceInstance;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import jakarta.annotation.PreDestroy;
import java.net.InetAddress;
import java.time.Instant;
import java.util.*;

/**
 * 注册中心服务
 * 负责管理服务实例的注册、注销和状态更新
 * 
 * @author nbsaas
 */
@Slf4j
@Service
public class RegistryService {

    @Value("${spring.application.name:nb-cloud-hub-gateway}")
    private String applicationName;
    
    @Value("${server.port:8080}")
    private int serverPort;
    
    @Value("${registry.nacos.server-addr:127.0.0.1:8848}")
    private String nacosServerAddr;
    
    @Value("${registry.nacos.namespace:public}")
    private String nacosNamespace;
    
    @Value("${registry.nacos.group:DEFAULT_GROUP}")
    private String nacosGroup;
    
    @Value("${registry.auto-register:false}")
    private boolean autoRegister;
    
    @Value("${registry.type:nacos}")
    private String defaultRegistryType;

    private final Map<String, RegistryAdapter> adapters = new HashMap<>();
    private ServiceInstance currentInstance;
    private final Set<String> registeredTypes = new HashSet<>();

    /**
     * Web服务器启动后的事件处理
     */
    @EventListener
    public void onWebServerInitialized(WebServerInitializedEvent event) {
        this.serverPort = event.getWebServer().getPort();
        initializeAdapters();
        createServiceInstance();
        
        if (autoRegister) {
            try {
                registerSelf(defaultRegistryType);
                log.info("自动注册到 {} 注册中心成功", defaultRegistryType);
            } catch (Exception e) {
                log.error("自动注册失败: {}", e.getMessage(), e);
            }
        }
    }

    /**
     * 初始化注册中心适配器
     */
    private void initializeAdapters() {
        try {
            // 初始化Nacos适配器
            NacosRegistryAdapter nacosAdapter = new NacosRegistryAdapter(
                nacosServerAddr, nacosNamespace, nacosGroup);
            adapters.put("nacos", nacosAdapter);
            log.info("Nacos适配器初始化成功: {}", nacosServerAddr);
        } catch (Exception e) {
            log.error("Nacos适配器初始化失败: {}", e.getMessage(), e);
        }

        try {
            // 初始化Polaris适配器
            PolarisRegistryAdapter polarisAdapter = new PolarisRegistryAdapter();
            adapters.put("polaris", polarisAdapter);
            log.info("Polaris适配器初始化成功");
        } catch (Exception e) {
            log.error("Polaris适配器初始化失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 创建当前服务实例
     */
    private void createServiceInstance() {
        try {
            String hostAddress = InetAddress.getLocalHost().getHostAddress();
            
            currentInstance = new ServiceInstance();
            currentInstance.setName(applicationName);
            currentInstance.setNamespace(nacosNamespace);
            currentInstance.setAddress("http://" + hostAddress + ":" + serverPort);
            currentInstance.setHealthCheckUrl("http://" + hostAddress + ":" + serverPort + "/api/status/health");
            currentInstance.setStatus("UP");
            currentInstance.setRegisteredAt(Instant.now());
            
            // 设置元数据
            Map<String, String> metadata = new HashMap<>();
            metadata.put("version", "1.0-SNAPSHOT");
            metadata.put("weight", "1.0");
            metadata.put("group", nacosGroup);
            metadata.put("management.port", String.valueOf(serverPort));
            metadata.put("service.type", "gateway");
            currentInstance.setMetadata(metadata);
            
            // 设置标签
            currentInstance.setTags(Arrays.asList("gateway", "hub", "cloud"));
            
            log.info("服务实例创建成功: {}", currentInstance.getName());
        } catch (Exception e) {
            log.error("创建服务实例失败: {}", e.getMessage(), e);
            throw new RuntimeException("创建服务实例失败", e);
        }
    }

    /**
     * 注册当前实例到指定类型的注册中心
     */
    public void registerSelf(String registryType) {
        RegistryAdapter adapter = adapters.get(registryType.toLowerCase());
        if (adapter == null) {
            throw new IllegalArgumentException("不支持的注册中心类型: " + registryType);
        }

        if (currentInstance == null) {
            throw new IllegalStateException("服务实例未初始化");
        }

        try {
            adapter.register(currentInstance);
            registeredTypes.add(registryType.toLowerCase());
            log.info("服务注册成功: {} -> {}", currentInstance.getName(), registryType);
        } catch (Exception e) {
            log.error("服务注册失败: {} -> {}, 错误: {}", currentInstance.getName(), registryType, e.getMessage(), e);
            throw new RuntimeException("服务注册失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从指定类型的注册中心注销当前实例
     */
    public void deregisterSelf(String registryType) {
        RegistryAdapter adapter = adapters.get(registryType.toLowerCase());
        if (adapter == null) {
            throw new IllegalArgumentException("不支持的注册中心类型: " + registryType);
        }

        if (currentInstance == null) {
            throw new IllegalStateException("服务实例未初始化");
        }

        try {
            adapter.deregister(currentInstance);
            registeredTypes.remove(registryType.toLowerCase());
            log.info("服务注销成功: {} -> {}", currentInstance.getName(), registryType);
        } catch (Exception e) {
            log.error("服务注销失败: {} -> {}, 错误: {}", currentInstance.getName(), registryType, e.getMessage(), e);
            throw new RuntimeException("服务注销失败: " + e.getMessage(), e);
        }
    }

    /**
     * 更新服务实例状态
     */
    public void updateStatus(String status, String registryType) {
        RegistryAdapter adapter = adapters.get(registryType.toLowerCase());
        if (adapter == null) {
            throw new IllegalArgumentException("不支持的注册中心类型: " + registryType);
        }

        if (currentInstance == null) {
            throw new IllegalStateException("服务实例未初始化");
        }

        try {
            currentInstance.setStatus(status);
            currentInstance.setLastHeartbeatTime(Instant.now());
            
            adapter.updateStatus(currentInstance, status);
            log.info("状态更新成功: {} -> {} ({})", currentInstance.getName(), status, registryType);
        } catch (Exception e) {
            log.error("状态更新失败: {} -> {} ({}), 错误: {}", currentInstance.getName(), status, registryType, e.getMessage(), e);
            throw new RuntimeException("状态更新失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取当前注册状态
     */
    public Map<String, Object> getRegistryStatus() {
        Map<String, Object> status = new HashMap<>();
        
        if (currentInstance != null) {
            status.put("serviceName", currentInstance.getName());
            status.put("address", currentInstance.getAddress());
            status.put("status", currentInstance.getStatus());
            status.put("registeredAt", currentInstance.getRegisteredAt());
            status.put("lastHeartbeat", currentInstance.getLastHeartbeatTime());
        }
        
        status.put("registeredTypes", new ArrayList<>(registeredTypes));
        status.put("availableAdapters", new ArrayList<>(adapters.keySet()));
        status.put("autoRegister", autoRegister);
        status.put("defaultRegistryType", defaultRegistryType);
        
        return status;
    }

    /**
     * 应用关闭时清理资源
     */
    @PreDestroy
    public void destroy() {
        log.info("开始清理注册中心资源...");
        
        // 注销所有已注册的服务
        for (String registryType : new HashSet<>(registeredTypes)) {
            try {
                deregisterSelf(registryType);
            } catch (Exception e) {
                log.warn("注销服务失败: {}", e.getMessage());
            }
        }
        
        // 关闭适配器连接
        adapters.values().forEach(adapter -> {
            if (adapter instanceof NacosRegistryAdapter) {
                ((NacosRegistryAdapter) adapter).close();
            }
        });
        
        log.info("注册中心资源清理完成");
    }
} 